using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Collections.Generic;
using System.Linq;
using System.ComponentModel;
using System.Web;
using System.Security.Permissions;
using Telerik.Web.UI;
using System.Collections;

//http://www.telerik.com/help/aspnet-ajax/grdpersistselectedrowsonsorting.html
namespace GenericControls {
   
    public class GenericControl<T> : CompositeControl where T : new()
    {
        #region Variables
        private RadGrid gvSource;
        private RadGrid gvDestination;
        
        private Button btnTransfer;
        private Button btnTransferBack;
        public delegate void OnTransferOccured(T transferedEntity,TransferDirection direction );
        public event OnTransferOccured Transfer;


        #endregion

        #region Properties

        [PersistenceMode(PersistenceMode.InnerProperty)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public FiledsCollection FieldsCollection { get; set; }

        public string Name { get; set; }
        
        public bool AutoGenerateColumns { get; set; }

        public int PageSize { get; set; }

        public int CurrentPageIndex 
        {

            get
            {
                if (ViewState["CurrentPageIndex"] != null)
                    return int.Parse(ViewState["CurrentPageIndex"].ToString());

                return 0;
            }
            set
            {
                ViewState["CurrentPageIndex"] = value;
            }
        }

        public bool AllowPaging { get; set; }

        public bool AllowSorting { get; set; }

        public List<T> SourceDataSource
        {
            get
            {
                if (ViewState["SourceDataSource"] == null)
                    throw new Exception("Data source is null");

                return ViewState["SourceDataSource"] as List<T>;
            }
            set
            {
                ViewState["SourceDataSource"] = value;
            }
        }

        public List<T> DestinationDataSource
        {
            get
            {
                return ViewState["DestinationDataSource"] as List<T>;

            }
            set
            {
                ViewState["DestinationDataSource"] = value;

            }
        }
       
        #endregion

        #region Methods

        #region DataSource

        private static List<T> LoadData(List<T> data)
        {
            return data;
        }

        public List<T> GetSourceDataSource()
        {
            return (List<T>)gvSource.DataSource;
        }

        public void SetSourceDataSource(List<T> dataSource)
        {

            gvSource.DataSource = dataSource;
            gvSource.DataBind();

        }

        private void SetDestinationDataSource(List<T> dataSource)
        {

            gvDestination.DataSource = dataSource;

            gvDestination.DataBind();

            DestinationDataSource = dataSource;

        }

        public List<T> GetDestinationDataSource()
        {

            return DestinationDataSource;

        }


        #endregion

        #region Events

        #region Page Events

        protected override void OnInit(EventArgs e)
        {
            base.OnInit(e);

        }

        protected override void CreateChildControls()
        {

            Controls.Clear();

            gvSource = new RadGrid();

            gvDestination = new RadGrid();

            btnTransfer = new Button();
            btnTransfer.Text = "Transfer";
            btnTransfer.Click += new EventHandler(btnTransfer_Click);



            btnTransferBack = new Button();
            btnTransferBack.Text = "TransferBack";
            btnTransferBack.Click += new EventHandler(btnTransferBack_Click);

            
            gvSource.PageIndexChanged += new GridPageChangedEventHandler(gvSource_PageIndexChanged);
            gvSource.NeedDataSource += new GridNeedDataSourceEventHandler(gvSource_NeedDataSource);
            gvSource.AllowPaging = (this.PageSize > 0) ? true : false;
            gvSource.PageSize = this.PageSize;
            gvSource.AutoGenerateColumns = this.AutoGenerateColumns;
            gvSource.AllowMultiRowSelection = true;
            
            GenerateGridColumns(FieldsCollection, gvSource);



            gvDestination.AutoGenerateColumns = this.AutoGenerateColumns;
            GenerateGridColumns(FieldsCollection, gvDestination);

            
            this.Controls.Add(gvSource);

            this.Controls.Add(gvDestination);

            this.Controls.Add(btnTransfer);

            this.Controls.Add(btnTransferBack);


        }

        

        void gvSource_NeedDataSource(object source, GridNeedDataSourceEventArgs e)
        {

            if (GetSourceDataSource() == null)
            {
                gvSource.DataSource = SourceDataSource;
             
            }   
        }

        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);
        }

      
        protected override void Render(HtmlTextWriter writer)
        {


            AddAttributesToRender(writer);

            gvSource.RenderControl(writer);

            gvDestination.RenderControl(writer);

            btnTransfer.RenderControl(writer);

            btnTransferBack.RenderControl(writer);


        }

        #endregion

        #region Control Events
      

        protected void btnTransfer_Click(object sender, EventArgs e)
        {
            if (gvSource.SelectedItems!=null && gvSource.SelectedItems.Count != 0)
            {

                List<T> datasource = SourceDataSource;

                if (datasource == null)
                    datasource = SourceDataSource;

                T selectedT = datasource.Skip(int.Parse(gvSource.SelectedIndexes[0]) + gvSource.PageSize * gvSource.CurrentPageIndex).First();

                if (SourceDataSource.Remove(selectedT))
                {
                    gvSource.DataSource = SourceDataSource;
                    gvSource.DataBind();
                }

                List<T> destinationDataSource = GetDestinationDataSource();

                if (destinationDataSource != null)
                {
                    destinationDataSource.Add(selectedT);
                }
                else
                {
                    destinationDataSource = new List<T>();
                    destinationDataSource.Add(selectedT);
                }

                SetDestinationDataSource(destinationDataSource);

                OnTransfer_EventHandler(selectedT, TransferDirection.forward);
            }
        }


        void btnTransferBack_Click(object sender, EventArgs e)
        {
            if (gvDestination.SelectedItems != null && gvDestination.SelectedItems.Count != 0)
            {

                List<T> datasource = DestinationDataSource;

                if (datasource == null)
                    datasource = DestinationDataSource;

                T selectedT = datasource.Skip(int.Parse(gvDestination.SelectedIndexes[0])).First();

                if (DestinationDataSource.Remove(selectedT))
                {
                    gvDestination.DataSource = DestinationDataSource;
                    gvDestination.DataBind();
                }

                List<T> sourceDataSource = SourceDataSource;

                if (sourceDataSource != null)
                {
                    sourceDataSource.Add(selectedT);
                }
                else
                {
                    sourceDataSource = new List<T>();
                    sourceDataSource.Add(selectedT);
                }

                SetSourceDataSource(sourceDataSource);

                OnTransfer_EventHandler(selectedT, TransferDirection.backward);

            }
        }


        void gvSource_PageIndexChanged(object source, GridPageChangedEventArgs e)
        {
            if (GetSourceDataSource() == null)
                SetSourceDataSource(SourceDataSource);

            gvSource.CurrentPageIndex = e.NewPageIndex;

            gvSource.Rebind();

        }

       


        #endregion
       
        #endregion

        #region Common Methods

        private void GenerateGridColumns(FiledsCollection FieldsCollection, RadGrid grid)
        {


          GridButtonColumn selectButton=new GridButtonColumn();

            selectButton.Text="Select";

            selectButton.CommandName="Select";

            grid.Columns.Add(selectButton);
            if (this.AutoGenerateColumns==false)
            {

                foreach (Field field in FieldsCollection)
                {

                    switch (field.Type)
                    {

                        default:
                        case Types.String:
                            GridBoundColumn boundColumn = new GridBoundColumn();
                            boundColumn.HeaderText = field.HeaderText;
                            boundColumn.DataType = Type.GetType("System.String");

                            boundColumn.DataField = field.DataField;
                            grid.Columns.Add(boundColumn);


                            break;

                        case Types.Number:
                            GridNumericColumn numericColumn = new GridNumericColumn();
                            numericColumn.HeaderText = field.HeaderText;
                            numericColumn.DataType = Type.GetType("System.Int32");
                            numericColumn.DataField = field.DataField;


                            grid.Columns.Add(numericColumn);


                            break;

                        case Types.DateTime:
                            GridDateTimeColumn dateTimeColumn = new GridDateTimeColumn();
                            dateTimeColumn.HeaderText = field.HeaderText;
                            dateTimeColumn.DataType = Type.GetType("System.DateTime");
                            dateTimeColumn.DataField = field.DataField;

                            grid.Columns.Add(dateTimeColumn);

                            break;
                    }

                }
            }
        }

        #endregion

        #endregion

        #region Explicit Page Events


        protected virtual void OnTransfer_EventHandler(T obj, TransferDirection direction)
        {
            if (Transfer != null)
                Transfer(obj, direction);
        }

        #endregion

    }
}
